/**
 * 游戏运行逻辑
 */
class Game {
    constructor(main) {
        let g = {
            main: main,         // 主函数
            actions: {},        // 记录按键动作
            keydowns: {},       // 记录按键keycode
            canvas: document.getElementById('canvas'),
            context: document.getElementById('canvas').getContext("2d"),
            fps: main.fps,
            timer: null,        // 轮询定时器
            state: 1,           // 游戏状态值，初始值为 1
            state_START: 1,
            state_RUNNING: 2,
            state_STOP: 3,
            state_GAMEOVER: 4,
            state_UPDATE: 5,
        }
        Object.assign(this, g)
    }
    // 绘制页面所有素材
    draw(paddle, ball, blockList, score) {
        let g = this
        // 清除画布
        g.context.clearRect(0, 0, g.canvas.width, g.canvas.height)
        // 绘制背景板
        g.drawBg()
        // 绘制砖块
        g.drawBlocks(blockList)
        // 绘制挡板
        g.drawImage(paddle)
        // 绘制小球
        g.drawImage(ball)
        // 绘制得分板
        g.drawText(score)
    }
    
    // 绘制图片素材
    drawImage(obj) {
        this.context.drawImage(obj.image, obj.x, obj.y)
    }
    // 绘制背景
    drawBg() {
        let bg = imageFromPath(allImg.background)
        this.context.drawImage(bg, 0, 0)
    }
    // 绘制砖块
    drawBlocks(list) {
        for (let item of list) {
            this.drawImage(item)
        }
    }
    // 绘制计数板键盘
    drawText(obj) {
        this.context.font = '24px Microsoft YaHei'
        this.context.fillStyle = '#fff'
        // 绘制分数
        this.context.fillText(obj.text + obj.allScore, obj.x, obj.y)
        // 绘制关卡
        this.context.fillText(obj.textLv + obj.lv, this.canvas.width - 100, obj.y)
    }

    // 注册事件
    registerAction(key, callback) {
        this.actions[key] = callback
    }
    // 游戏结束
  gameOver () {
    // 清除定时器
    clearInterval(this.timer)
    // 清除画布
    this.context.clearRect(0, 0, this.canvas.width, this.canvas.height)
    // 绘制背景图
    this.drawBg()
    // 绘制提示文字
    this.context.font = '48px Microsoft YaHei'
    this.context.fillStyle = '#fff'
    this.context.fillText('游戏结束', 404, 226)
  }
  // 游戏晋级
  goodGame () {
    // 清除定时器
    clearInterval(this.timer)
    // 清除画布
    this.context.clearRect(0, 0, this.canvas.width, this.canvas.height)
    // 绘制背景图
    this.drawBg()
    // 绘制提示文字
    this.context.font = '48px Microsoft YaHei'
    this.context.fillStyle = '#fff'
    this.context.fillText('恭喜晋级下一关卡', 308, 226)
  }
  // 游戏通关
  finalGame () {
    // 清除定时器
    clearInterval(this.timer)
    // 清除画布
    this.context.clearRect(0, 0, this.canvas.width, this.canvas.height)
    // 绘制背景图
    this.drawBg()
    // 绘制提示文字
    this.context.font = '48px Microsoft YaHei'
    this.context.fillStyle = '#fff'
    this.context.fillText('恭喜通关全部关卡', 308, 226)
  }


    // 小球碰撞砖块检测
  checkBallBlock (g, paddle, ball, blockList, score) {
    let p = paddle, b = ball
    // 小球碰撞挡板检测
    if (p.collide(b)) {
      // 当小球运动方向趋向挡板中心时，Y轴速度取反，反之则不变
      if (Math.abs(b.y + b.h/2 - p.y + p.h/2) > Math.abs(b.y + b.h/2 + b.speedY - p.y + p.h/2)) {
        b.speedY *= -1
      } else {
        b.speedY *= 1
      }
      // 设置X轴速度
      b.speedX = p.collideRange(b)
    }
    // 小球碰撞砖块检测
    blockList.forEach(function (item, i, arr) {
      if (item.collide(b)) { // 小球、砖块已碰撞
        if (!item.alive) { // 砖块血量为0时，进行移除
          arr.splice(i, 1)
        }
        // 当小球运动方向趋向砖块中心时，速度取反，反之则不变
        if ((b.y < item.y && b.speedY < 0) || (b.y > item.y && b.speedY > 0)) {
          if (!item.collideBlockHorn(b)) {
            b.speedY *= -1
          } else { // 当小球撞击砖块四角时，Y轴速度不变
            b.speedY *= 1
          }
        } else {
          b.speedY *= 1
        }
        // 当小球撞击砖块四角时，X轴速度取反
        if (item.collideBlockHorn(b)) {
          b.speedX *= -1
        }
        // 计算分数
        score.computeScore()
      }
    })
    // 挡板移动时边界检测
    if (p.x <= 0) { // 到左边界时
      p.isLeftMove = false
    } else {
      p.isLeftMove = true
    }
    if (p.x >= 1000 - p.w) { // 到右边界时
      p.isRightMove = false
    } else {
      p.isRightMove = true
    }
    // 移动小球
    b.move(g)
  }
    // 设置逐帧动画
    setTimer(paddle, ball, blockList, score) {
        let g = this
        let main = g.main
        g.timer = setInterval(function () {
            // actions 集合
            let actions = Object.keys(g.actions)
            for (let i = 0; i < actions.length; i++) {
                let key = actions[i]
                if (g.keydowns[key]) {
                    g.actions[key]()
                }
            }
            // 游戏开始时，执行的事件
            if (g.state == g.state_RUNNING) {
                g.checkBallBlock(g, paddle, ball, blockList, score)
                // 绘制所有游戏素材
                g.draw(paddle, ball, blockList, score)
            } else if (g.state == g.state_START) {
                // 绘制所有素材
                g.draw(paddle, ball, blockList, score)
            }
        }, 1000/g.fps)
    }
    
    
    // 初始化游戏
    init() {
        let g = this
        let blockList = g.main.blockList
        let paddle = g.main.paddle
        let score = g.main.score
        let ball = g.main.ball
        // 设置按键监听，注册相关函数
        window.addEventListener('keydown', (event) => {
            g.keydowns[event.keyCode] = true
        })
        window.addEventListener('keyup', (event) => {
            g.keydowns[event.keyCode] = false
        })
        g.registerAction = function(key, callback) {
            g.actions[key] = callback
        }
        // 注册左方向键移动事件
        g.registerAction('37', function() {
            if (g.state === g.state_RUNNING && paddle.isLeftMove) {
                paddle.moveLeft()
            }
        })
        // 注册右方向键移动事件
        g.registerAction('39', function() {
            if (g.state === g.state_RUNNING && paddle.isRightMove) {
                paddle.moveRight()
            }
        })

        window.addEventListener('keydown', function(event) {
            switch (event.keyCode) {
                case 32:
                    // 空格键，游戏开始键
                    if (g.state === g.state_GAMEOVER) {
                        // 游戏结束时，重新开始游戏
                        g.state = g.state_START
                        // 初始化
                        g.main.start()
                    } else {
                        g.state = g.state_RUNNING
                    }
                    break

                case 80:
                    //  P键，暂停键
                    g.state = g.state_STOP
                    break
            }
        })
        // 设置轮询定时器
        g.setTimer(paddle, ball, blockList, score)
    }

}